std::unique_ptr provide already the right overload but you need std::move to use them as unique_ptr is not copyable :
std::unique_ptr<X> x;
std::unique_ptr<Y> y { new Y };
x = std::move(y);
For the very specific question, there is no cast possible, if you need to received unique_ptr of sub classes by reference, then use a template function.
template < typename T, typename = typename std::enable_if< std::is_base_of<X,T>::value>::type >
void foo( std::unique_ptr<T> & ) {
}
And last, as the idea is to get ownership of the pointer, if you pass the unique_ptr by rvalue reference, this works as you wants.
void bar( std::unique_ptr<X> && ) {
}
// then
bar( std::move(y) );