Well, UTexture is an abstract class that cannot be instantiated. It relies on it’s concrete subclasses UTexture2D, UTextureCube, UTexture2DArray, etc to be instantiated. If you have a pointer to a UTexture, then it actually IS a UTexture2D, or UTextureCube, or UTexture2DArray etc.
So what you can do i believe, is simply cast it like so.
if(const auto Texture2D = Cast<UTexture2D>(Texture))
{
//If This block is reached, the texture was a Texture2D. Lets do our work with it
// Make Sure The Texture Is Up To Date.
Texture2D->UpdateResource();
// Get Platform Data.
const auto PlatformData = Texture2D->GetPlatformData();
// Get The Bulk Data
const auto TextureData = PlatformData->Mips[0].BulkData;
// Array Pixel Data Will Be Copied To
TArray<FColor> DestPixels{};
// Initialize The Array With The Correct Pixel Size;
DestPixels.AddDefaulted(PlatformData->SizeX * PlatformData->SizeY);
// Lock The Pixel Data For CPU Read Access.
const auto PixelData = static_cast<const FColor*>(TextureData.LockReadOnly());
// Copy The Pixel Data.
FMemory::Memcpy(DestPixels.GetData(), &PixelData, sizeof(FColor) * DestPixels.Num());
// Unlock So The GPU Can Access The Data Again.
TextureData.Unlock();
// We Now Have All Pixel Data For The Texture And We Can Do What We Want Without Holding The GPU Up.
DestPixels
}