def union(self, other, sort=None):
        self._validate_sort_keyword(sort)
        self._assert_can_do_setop(other)
        other = ensure_index(other)
        if len(other) == 0 or self.equals(other):
            return self._get_reconciled_name_object(other)
        if len(self) == 0:
            return other._get_reconciled_name_object(self)
        if not is_dtype_union_equal(self.dtype, other.dtype):
            this = self.astype('O')
            other = other.astype('O')
            return this.union(other, sort=sort)
        if is_period_dtype(self) or is_datetime64tz_dtype(self):
            lvals = self._ndarray_values
        else:
            lvals = self._values
        if is_period_dtype(other) or is_datetime64tz_dtype(other):
            rvals = other._ndarray_values
        else:
            rvals = other._values
        if sort is None and self.is_monotonic and other.is_monotonic:
            try:
                result = self._outer_indexer(lvals, rvals)[0]
            except TypeError:
                result = list(lvals)
                value_set = set(lvals)
                result.extend([x for x in rvals if x not in value_set])
        else:
            indexer = self.get_indexer(other)
            indexer, = (indexer == -1).nonzero()
            if len(indexer) > 0:
                other_diff = algos.take_nd(rvals, indexer,
                                           allow_fill=False)
                result = _concat._concat_compat((lvals, other_diff))
            else:
                result = lvals
            if sort is None:
                try:
                    result = sorting.safe_sort(result)
                except TypeError as e:
                    warnings.warn("{}, sort order is undefined for "
                                  "incomparable objects".format(e),
                                  RuntimeWarning, stacklevel=3)
        return self._wrap_setop_result(other, result)