Is there any way to make an UTXO that cannot be spent until a certain block #?
No, there isn't currently any way to do what you describe without using a third-party oracle.

Yes, you may be able to do this relatively soon.  A soft fork has been proposed to introduce a OP_CHECKLOCKTIMEVERIFY op code` (CLTV), and what what I can tell it has strong support from the core dev team (but note that soft forks require miner support for implementation).

As Nick says, previous attempts were rejected because they proposed pushing the current block's height or time on to the stack like this:

&lt;pubkey&gt;       checksigverify  block           &lt;data&gt;    equalverify
&lt;your pubkey&gt;  compare to sig  current height  1000000   Only spend in block 1,000,000


Again, elaborating on what Nick said, the example transaction above would be valid in block 1,000,000---but if there was a chain reorganization, it might not be included in the new block 1,000,000 and so any transactions depending on it would be invalid.

The CLTV op code avoids this two ways.  First, it use the nLockTime value from the spending transaction rather than the block height or block header time value.  Since a transaction can only be included in a block if its nLockTime is equal to or greater than the current block height/time, this achieves the primary goal of allowing UTXOs that can't be spent until a particular time.

The other thing CLTV does is check values directly rather than pushing data to the stack.  This allows it to only implement a greater-than-or-equal-to check, so the transaction is always spendable after the specified height/time.

My guess is that the soft fork process to introduce CLTV will begin with Bitcoin Core 0.11, possibly sometime around July 2015.  (But, really, the core devs are unlikely to spend much time on CLTV until 0.10 gets released around January, so don't count on it.)