Encontré cómo resolverlo, así que espero que esto sea útil para alguien.
Primero, SQL_Latin1_General_CP1_CI_AS es una mezcla extraña de CP-1252 y UTF-8. Los caracteres básicos son CP-1252, por lo que todo lo que tenía que hacer era UTF-8 y todo funcionó. Los caracteres asiáticos y otros UTF-8 están codificados en 2 bytes y el controlador php pdo_mssql parece odiar los caracteres de longitud variable, por lo que parece hacer un CAST a varchar (en lugar de nvarchar) y luego todos los caracteres de 2 bytes se convierten en signos de interrogación (' ?').
Lo arreglé convirtiéndolo en binario y luego reconstruí el texto con php:
SELECT CAST(MY_COLUMN AS VARBINARY(MAX)) FROM MY_TABLE;
En PHP:
//Binary to hexadecimal
$hex = bin2hex($bin);
//And then from hex to string
$str = "";
for ($i=0;$i<strlen($hex) -1;$i+=2)
{
$str .= chr(hexdec($hex[$i].$hex[$i+1]));
}
//And then from UCS-2LE/SQL_Latin1_General_CP1_CI_AS (that's the column format in the DB) to UTF-8
$str = iconv('UCS-2LE', 'UTF-8', $str);