Without REPLACE INTO or INSERT ON DUPLICATE KEY UPDATE, you need to find out which records should be updated or inserted. I had to do something like this in cases where there was no composite primary key, but it would work as a substitute for REPLACE INTO.
- Create a temporary table that has the columns to be INSERTED or UPDATED. Also in this temp table you need a "found" column of type BIT
- Put the rows that are to be inserted or updated into this temp table. Leave "found" as 0.
- Do UPDATE temporary table SET found = 1 and join to your destination table.
- Update your destination table JOINed to the temporary table on the primary key (or unique key) fields.
- INSERT into the destination table everything from the temporary table where found = 0.
SQL coming as soon as the page will let me post it, having technical issues here. For now, added a picture.

EDIT: The SQL in the picture, in TEXT format:
DROP TABLE IF EXISTS
CREATE TABLE #tmp (
col_1, col_2, col_n
found bit NOT NULL DEFAULT 0,
PRIMARY KEY CLUSTERED (pkey_column1, pkey_column2, pkey_column_n)
);
INSERT INTO #tmp (col_1, col_2, col_n)
SELECT
col_1, col_2, col_n
FROM source_table;
UPDATE a
SET
a.found = 1
FROM #tmp a
INNER JOIN destination_table b
ON a.pkey_column_1 = b.pkey_column_1
AND a.pkey_column_2 = b.pkey_column_2
AND a.pkey_column_n = b.pkey_column_n;
UPDATE b
SET
b.col_1 = a.col_1,
b.col_2 = a.col_2,
b.col_n = a.col_n
FROM #tmp a
INNER COIN destination_table_b
ON a.pkey_column_1 = b.pkey_column_1
AND a.pkey_column_2 = b.pkey_column_2
AND a.pkey_column_n = b.pkey_column_n;
INSERT INTO destination_table
(col_1, col2, col_n)
SELECT
col1_, col_2, col_n
FROM #tmp
WHERE found = 0
MERGEstatement