First i manipulate the data into required format
IF OBJECT_ID('tempdb..##Getdata')IS NOT NULL
DROP TABLE ##Getdata
;With cte(Person, Color)
AS
(
SELECT 'Alex'    , 'red'    UNION ALL
SELECT 'Alex'    , 'blue'   UNION ALL
SELECT 'Alex'    , 'orange' UNION ALL
SELECT 'Mike'    , 'green'  UNION ALL
SELECT 'Tom'     , 'blue'   UNION ALL
SELECT 'Tom'     , 'black' 
)
,Cte_Final
AS
(
SELECT DENSE_RANK()OVER(ORDER BY Person )AS Rnk
      ,Person
      ,Color 
      ,'Color_'+CAST(DENSE_RANK()OVER(ORDER BY Person ) AS VARCHAR(2)) AS ColrCol
 FROM cte
)
SELECT DISTINCT Rnk
        ,Person
        ,ColrCol
        ,STUFF((SELECT DISTINCT  ', '+Color 
                    FROM Cte_Final i WHERE i.Rnk=o.Rnk
                 FOR XML PATH ('')),1,1,'') AS
                  Color
    INTO ##Getdata
FROM Cte_Final o
Using Dynamic Sql i get the expected result
DECLARE @COlumn nvarchar(max),@Sql nvarchar(max)
SELECT  @COlumn=STUFF((SELECT DISTINCT  ', '+'Split.a.value(''/S['+CAST(Rnk AS VARCHAR(2))+']'''+','+'''nvarchar(100)'''+') As '  + QUOTENAME(ColrCol )
                    FROM ##Getdata i
                 FOR XML PATH ('')),1,1,'') 
SET @Sql='SELECT DISTINCT Person,'+@COlumn+' FROM
            (
            SELECT Person, 
            CAST(''<S>''+REPLACE (Color,'','',''</S><S>'')+''</S>'' AS XML ) AS Color
            FROM ##Getdata
            ) AS A
            CROSS APPLY Color.nodes(''S'') AS Split(a)
            '
PRINT @Sql
EXEC(@Sql)
Result
Person  Color_1 Color_2  Color_3
--------------------------------
Alex     blue    orange  red
Mike     green   NULL    NULL
Tom      black   blue    NULL
view demo from below link
Expected Result for your data