If the keys are being generated from a sequence, then the normal way to get the key generated by that insert is to use the returning clause:
declare
  v_insert_seq integer;
begin
  insert into t1 (pk, c1)
  values (myseq.nextval, 'value') returning pk into v_insert_seq;
end;
/
However, as best as I can tell, the merge statement doesn't support that returning feature.
Depending on the source of your new rows, there are different ways you could do this. If you are inserting one row at a time, then the approach above will work pretty well.
To detect the duplicate records, just catch the exceptions when you are inserting (when dup_val_on_index) and then handle them with updates.
If your source of rows is another table, you probably want to look at bulk inserts, and allowing Oracle to return you an array of new PK values. I tried this, but couldn't get it working, so perhaps it's not supported (or I'm missing something today - it gives a syntax error):
declare
  type t_type is table of t1.pk%type;
  v_insert_seqs t_type;
begin
   insert into t1 (pk, c1)
   select level newpk, 'value' c1value
   from dual
   connect by level <= 10 returning pk bulk collect into v_insert_seqs;
exception 
  when dup_val_on_index then
    raise;
end;
/
The next best thing is to select the rows into arrays and then use bulk binds with the returning clause to capture the new PK IDs and also use Save Exceptions to catch all the rows that failed to inserted. Then you can process any of the failed inserted afterwards:
set serveroutput on
declare
  type t_pk is table of t1.pk%type;
  type t_c1 is table of t1.c1%type;
  v_pks t_pk;
  v_c1s  t_c1;
  v_new_pks t_pk;
  ex_dml_errors EXCEPTION;
  PRAGMA EXCEPTION_INIT(ex_dml_errors, -24381);
begin
  -- get the batch of rows you want to insert
  select level newpk, 'value' c1
  bulk collect into v_pks, v_c1s
  from dual connect by level <= 10;
  -- bulk bind insert, saving exceptions and capturing the newly inserted
  -- records
  forall i in v_pks.first .. v_pks.last save exceptions 
    insert into t1 (pk, c1)
    values (v_pks(i), v_c1s(i)) returning pk bulk collect into v_new_pks;
exception
 -- Process the exceptions 
  when ex_dml_errors then
    for i in 1..SQL%BULK_EXCEPTIONS.count loop
      DBMS_OUTPUT.put_line('Error: ' || i || 
          ' Array Index: ' || SQL%BULK_EXCEPTIONS(i).error_index ||
          ' Message: ' || SQLERRM(-SQL%BULK_EXCEPTIONS(i).ERROR_CODE));
    end loop;
end;
/